package com.abel.bigwater.dataserver.model.h86a

import com.abel.bigwater.dataserver.model.PacketException
import com.abel.bigwater.dataserver.model.hgd.*
import io.netty.buffer.ByteBuf
import org.joda.time.DateTime
import org.joda.time.format.DateTimeFormat
import org.slf4j.LoggerFactory
import java.text.SimpleDateFormat

/**
 * 3.3 实时数据协议
 * 监控仪主动向总台上发的数据以打包的形式上发。
 * 系统主动上传数据格式:
 * 例：以下为流量计上传的数据，一个脉冲表示一吨水，断电和来电都报警。
 * ST:00001; 05/01/13 10:00;P1:01234567;L1:00000200;P2:23456789;
 * L2:00000150; B4:0;A5:95.73;A6:86.42;V:7.10;H:018.
 * 注释：
 * ST：00001 该点站号为1号站；
 * 05/01/13/10：00 发这条数据的时间为05年1月13日10点；
 * P1：01234567 第一路累计流量为1234567吨水；
 * L1：00000200 其中昨天24小时(零点到零点)累计200吨水；
 * P2：23456789 第二路累计流量为23456789吨水；
 * L2：00000150 其中昨天24小时累计150吨水；
 * B4：0 报警量为0，表示目前有市电；
 * A5：95.73 第五路瞬时流量为95.73吨水每小时；
 * A6：86.42 第六路瞬时流量为86.42吨水每小时；
 * V：7.10 后备电池电压为7.10V；
 * H:018 短信共计18次。
 * 以上数据信息中，通道3和通道4没有用起来。
 * 注：P—脉冲，A—模拟，K—开关量，B—报警量。
 *
 *
 * @author Abel
 */
class H86ARealtimeData : HgdUdpData {

    constructor() : super(HgdaoBase.TYPE_TCP)

    /**
     * @param type
     */
    constructor(type: String) : super(type)

    /**
     * 53 54 3A 31 30 30 30 30 3B 31 36 2F 30 39 2F 30 38 20 32 33 3A 35 30 3B 50 31 3A 30 30 30 30 30 30 30 30 30 3B 50
     * 32 3A 30 30 30 30 30 30 30 30 30 3B 4B 33 3A 31 3B 4B 34 3A 31 3B 41 31 3A 30 2E 30 30 30 3B 41 32 3A 30 2E 30 30
     * 30 3B 48 3A 30 30 32 3B 53 3A 32 33 2E 0D 0A
     *
     * 32 32 3A 31 30 30 30 30 0D 0A 40 32 32 32 3A 31 30 30 30 30 0D 0A 53 54 3A 31 30 30 30 30 3B 31 36 2F 30 39 2F 30
     * 39 20 30 30 3A 30 30 3B 50 31 3A 30 30 30 30 30 30 30 30 30 3B 50 32 3A 30 30 30 30 30 30 30 30 30 3B 4B 33 3A 31
     * 3B 4B 34 3A 31 3B 41 31 3A 30 2E 30 30 30 3B 41 32 3A 30 2E 30 30 30 3B 48 3A 30 30 31 3B 53 3A 32 34 2E 0D 0A
     *
     * @222:10000
     * ST:10000;16/09/09 00:00;P1:000000000;P2:000000000;K3:1;K4:1;A1:0.000;A2:0.000;H:001;S:24.
     *
     * ST:00002;16/09/11
     * 17:58;P1:00000055;L1:00000000;P2:00000001;L2:00000000;P3:00000000;L3:00000000;A3:0.000;V:6.79;H:000.
     *
     * @param buf
     * @return
     * @throws PacketException
     */
    @Throws(PacketException::class)
    override fun parseBuffer(buf: ByteBuf, ignoreChecksum: Boolean): Boolean {
        if (buf.readableBytes() < 3 + 5 + 2) return false

        // ST: not this type
        buf.duplicate().apply {
            val st = readBytes(3).toString(Charsets.ISO_8859_1)
            if (st != "ST:") return false
        }

        buf.readBytes(Math.min(MAX_LENGTH, buf.readableBytes())).toString(Charsets.ISO_8859_1).apply {
            fmt = this

            // parse key-value list.
            val kvList = this.split(";")
            if (kvList.size > 2) {
                station = kvList[0].substring(3)

                startTime = SimpleDateFormat("yy/MM/dd HH:mm").parse(kvList[1])

                for (i in 3..kvList.count()) {
                    val temp = kvList[i - 1].trim()
                    val kv = temp.split(":")
                    if (kv.size > 1) {
                        var hc: HgdChannel<*>? = null

                        when {
                            kv[0].startsWith(HgdChannelType.PULSE_TYPE.abbr) -> {
                                hc = PulseChannel(1)
                                hc.channel = kv[0].substring(1).toShort()
                                hc.values.add(kv[1].toLong())
                            }

                            kv[0].startsWith(HgdChannelType.ANALOG_TYPE.abbr) -> {
                                hc = AnalogChannel(1)
                                hc.channel = kv[0].substring(1).toShort()
                                hc.values.add(kv[1].toFloat())
                            }

                            kv[0].startsWith(HgdChannelType.K_TYPE.abbr) -> {
                                hc = KChannel(1)
                                hc.channel = kv[0].substring(1).toShort()
                                hc.values.add(kv[1].toByte())
                            }

                            kv[0].startsWith(HgdChannelType.B_TYPE.abbr) -> {
                                hc = BChannel(1)
                                hc.channel = kv[0].substring(1).toShort()
                                hc.values.add(kv[1].toByte())
                            }

                            kv[0].startsWith(HgdChannelType.M_TYPE.abbr) -> {
                                hc = MChannel(1)
                                hc.channel = kv[0].substring(1).toShort()
                                hc.values.add(kv[1].toInt())
                            }

                            kv[0].startsWith(HgdChannelType.Q_TYPE.abbr) -> {
                                hc = QChannel(1)
                                hc.channel = kv[0].substring(1).toShort()
                                hc.values.add(kv[1].toShort())
                            }

                            kv[0].startsWith('V') -> {
                                voltage = kv[1].toFloat().times(100.0F).toInt()
                            }

                            kv[0].startsWith('L') -> {
                            }

                            kv[0].startsWith('H') -> {

                            }

                            kv[0].startsWith('S') -> {

                            }

                            else -> hc = null
                        }

                        if (hc != null) {
                            channelList.add(hc)
                        }
                    }
                }
            }
        }

        return true
    }

    override fun toString(): String {
        return "${javaClass.simpleName}[$station->$startTime, ${channelList.size}]"
    }

    companion object {

        private val log = LoggerFactory.getLogger(H86ARealtimeData::class.java)

        private const val MAX_LENGTH: Int = 2048
    }

}
